﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="SchemaRepositoryDs.cs" company="Data Ductus Malmö">
//   (c) 2010 - 2012 Data Ductus Malmö AB
// </copyright>
// --------------------------------------------------------------------------------------------------------------------

namespace DataDuctus.Snmp.Persistor.Core.Schema
{
  using System.Collections.Generic;

  using Lextm.SharpSnmpLib;

  /// <summary>
  /// The schema repository ds.
  /// </summary>
  public class SchemaRepositoryDs
  {
    #region Fields

    /// <summary>
    /// The repos.
    /// </summary>
    private readonly SchemaRepository repos;

    /// <summary>
    /// The alias tables.
    /// </summary>
    private IDictionary<string, SchemaRepositoryDsTable> aliasTables = new Dictionary<string, SchemaRepositoryDsTable>();

    /// <summary>
    /// The tables.
    /// </summary>
    private IDictionary<string, SchemaRepositoryDsTable> tables = new Dictionary<string, SchemaRepositoryDsTable>();

    #endregion

    #region Constructors and Destructors

    /// <summary>
    /// Initializes a new instance of the <see cref="SchemaRepositoryDs"/> class.
    /// </summary>
    /// <param name="repos">
    /// The repos.
    /// </param>
    public SchemaRepositoryDs(SchemaRepository repos)
    {
      this.repos = repos;

      this.ReIndex();
    }

    #endregion

    #region Public Properties

    /// <summary>
    /// Gets the tables.
    /// </summary>
    public ICollection<SchemaRepositoryDsTable> Tables
    {
      get
      {
        return this.tables.Values;
      }
    }

    #endregion

    #region Public Indexers

    /// <summary>
    /// The this.
    /// </summary>
    /// <param name="path">
    /// The path.
    /// </param>
    /// <returns>
    /// The SnmpPersistor.Core.Schema.SchemaRepositoryDsTable.
    /// </returns>
    public SchemaRepositoryDsTable this[string path]
    {
      get
      {
        if (this.tables.ContainsKey(path))
        {
          return this.tables[path];
        }

        if (this.aliasTables.ContainsKey(path))
        {
          return this.aliasTables[path];
        }

        return SchemaRepositoryDsTable.EmptyTable;
      }
    }

    #endregion

    #region Methods

    /// <summary>
    /// The re index.
    /// </summary>
    internal void ReIndex()
    {
      IDictionary<string, SchemaRepositoryDsTable> tbl = new Dictionary<string, SchemaRepositoryDsTable>();
      IDictionary<string, SchemaRepositoryDsTable> aliasTbl = new Dictionary<string, SchemaRepositoryDsTable>();

      ReIndex(this.repos.Root, tbl, aliasTbl);
      this.tables = tbl;
      this.aliasTables = aliasTbl;
    }

    /// <summary>
    /// The re index.
    /// </summary>
    /// <param name="node">
    /// The node.
    /// </param>
    /// <param name="tbl">
    /// The tbl.
    /// </param>
    /// <param name="aliasTbl">
    /// The alias tbl.
    /// </param>
    private static void ReIndex(
      ISchemaItem node, 
      IDictionary<string, SchemaRepositoryDsTable> tbl, 
      IDictionary<string, SchemaRepositoryDsTable> aliasTbl)
    {
      if (null == node)
      {
        return;
      }

      bool foundScalarTable = false;

      foreach (ISchemaItem n in node.Children)
      {
        if (n.Type == DefinitionType.Table)
        {
          string fqName = n.NameSpace + "." + n.Name;
          var table = new SchemaRepositoryDsTable(fqName, n);

          tbl.Add(fqName, table);

          if (!aliasTbl.ContainsKey(table.Name))
          {
            aliasTbl.Add(table.Name, table);
          }
        }
        else if (!foundScalarTable && n.Type == DefinitionType.Scalar)
        {
          string fqName = n.ParentItem.NameSpace + "." + n.ParentItem.Name;
          var table = new SchemaRepositoryDsTable(fqName, n.ParentItem);

          tbl.Add(fqName, table);

          if (!aliasTbl.ContainsKey(table.Name))
          {
            aliasTbl.Add(table.Name, table);
          }

          foundScalarTable = true;
        }
        else
        {
          ReIndex(n, tbl, aliasTbl);
        }
      }
    }

    #endregion
  }
}